package dao

import (
	"context"
	"errors"
	"fmt"
	"mini-app/internal/dal"

	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"github.com/samber/lo"

	"mini-app/internal/define"
	"mini-app/internal/models"
	"strconv"
	"strings"
	"time"

	"gorm.io/gorm"
)

type OnlineEvent struct{}

// Create 创建在线活动
func (OnlineEvent) Create(ctx context.Context, db *gorm.DB, record models.OnlineEvent) (string, error) {
	err := db.WithContext(ctx).Model(&models.OnlineEvent{}).Create(&record).Error
	return record.ID, err
}

// Update 在线活动更新
func (OnlineEvent) Update(ctx context.Context, db *gorm.DB, record models.OnlineEvent) error {
	var recordMap = make(map[string]interface{})
	if record.Name != "" {
		recordMap["name"] = record.Name
	}
	if record.StartTime > 0 && record.EndTime > 0 {
		recordMap["start_time"] = record.StartTime
		recordMap["end_time"] = record.EndTime
	}
	recordMap["require_points"] = record.RequirePoints
	recordMap["require_supporters"] = record.RequireSupporters
	recordMap["express_fee"] = record.ExpressFee
	if record.GoodsID != "" {
		recordMap["goods_id"] = record.GoodsID
	}
	recordMap["limited_free"] = record.LimitedFree
	if record.Image != "" {
		recordMap["image"] = record.Image
	}
	recordMap["purchase_method"] = record.PurchaseMethod
	recordMap["goods_link"] = record.GoodsLink
	recordMap["description"] = record.Description
	recordMap["base_joined_user"] = record.BaseJoinedUser
	recordMap["check_gender_type"] = record.CheckGenderType

	return db.WithContext(ctx).Model(&models.OnlineEvent{}).
		Where("id = ?", record.ID).
		Updates(recordMap).Error
}

// End 更新活动的状态为已结束(主要表示已经抽过奖品)
func (OnlineEvent) End(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
) bool {
	rowsAffected := db.WithContext(ctx).Model(&models.OnlineEvent{}).
		Where("id = ?", onlineEventID).
		Update("status", 3).
		RowsAffected
	return rowsAffected == 1
}

// 设置已开奖
func (OnlineEvent) SetDraw(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
) bool {
	rowsAffected := db.WithContext(ctx).Model(&models.OnlineEvent{}).
		Where("id = ?", onlineEventID).
		Update("is_draw", 1).
		RowsAffected

	return rowsAffected == 1
}

// Delete 删除在线活动
func (OnlineEvent) Delete(ctx context.Context, db *gorm.DB, ID string) error {
	return db.WithContext(ctx).Model(&models.OnlineEvent{}).
		Where("id = ?", ID).
		Delete(&models.OnlineEvent{}).Error
}

// Detail 在线活动详情
func (OnlineEvent) Detail(ctx context.Context, db *gorm.DB, ID string) *models.OnlineEvent {
	var record models.OnlineEvent
	rowsAffected := db.WithContext(ctx).Model(&models.OnlineEvent{}).
		Where("id = ?", ID).
		Take(&record).RowsAffected
	if rowsAffected <= 0 {
		return nil
	}
	return &record
}

// List 在线活动列表
func (OnlineEvent) List(
	ctx context.Context,
	db *gorm.DB,
	name string,
	status int,
	visible int,
	enableAutoInvisible int,
	page, limit int,
) (list []models.OnlineEvent, total int64) {
	tx := db.WithContext(ctx).Model(&models.OnlineEvent{})
	if name != "" {
		tx = tx.Where("name LIKE ?", "%"+name+"%")
	}
	// 活动状态
	now := time.Now()
	newTs := now.Unix()
	switch status {
	case 1: // 进行中
		tx = tx.Where("start_time <= ? AND end_time >= ? and status = 0", newTs, newTs)
	case 2: // 未开始
		tx = tx.Where("start_time > ? AND status = 0", newTs)
	case 3: // 已结束
		tx = tx.Where("end_time < ? OR status = ?", newTs, 3)
	}

	// 活动结束后30天，不显示
	nowBefore30Days := now.AddDate(0, 0, -30)
	if enableAutoInvisible == define.State_Yes {
		tx = tx.Where("end_time > ?", nowBefore30Days.Unix())
	}

	if visible == define.State_Yes {
		// 记录visible为0，表示默认值（显示），所以用visible != 2来作为条件
		tx = tx.Where("visible != ?", define.State_No) //设置了不可显示标志时，不显示
	} else if visible == define.State_No {
		// 默认显示
		tx = tx.Where("visible = ?", define.State_No)
	}

	tx.Count(&total)
	if limit > 0 {
		if limit > 2000 {
			limit = 2000
		}
		tx = tx.Limit(limit)
	}
	if page > 0 && limit > 0 {
		tx = tx.Offset((page - 1) * limit)
	}

	/*
			排序优先级：
		    top>已开始> 未开始> 已结束
			1. top字段非0时，优先按top降序排列
			2. 按活动状态和时间条件分组：已开始 > 未开始 > 已结束
			3. 在每个状态分组内部，按sort字段降序排列
			4. 最后按id升序排列保证稳定性

			状态优先级数字：
			1：正在进行中的活动（当前时间在 start_time 和 end_time 之间）
			2：即将开始的活动（start_time 大于当前时间）
			3：已结束的活动或状态为3的活动
	*/
	tx.Order(`
        CASE WHEN top != 0 THEN 0 ELSE 1 END ASC,
        top DESC,
        CASE
			WHEN status = 3 THEN 3
            WHEN start_time <= UNIX_TIMESTAMP() AND end_time >= UNIX_TIMESTAMP() THEN 1
            WHEN start_time > UNIX_TIMESTAMP() THEN 2
            WHEN end_time < UNIX_TIMESTAMP() THEN 3
            ELSE 3
        END
        ASC,sort DESC,id ASC`).
		Omit("selected_user", "description").
		Find(&list)

	//for i, v := range list {
	//	if v.EndTime < nowBefore30Days.Unix() {
	//		list[i].Visible = define.State_No
	//		continue
	//	}
	//}
	return list, total
}

// WinnerConfig 中奖配置
func (t OnlineEvent) WinnerConfig(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
	userID string,
	puppetUserID string,
) error {
	err := t.ValidateUserIDs(userID)
	if err != nil {
		return fmt.Errorf("用户ID格式错误：")
	}

	err = t.ValidateUserIDs(puppetUserID)
	if err != nil {
		return fmt.Errorf("马甲ID格式错误：")
	}

	parsedUserIDs, _ := t.ParsedUserIDs(userID)
	parsedPuppetUserIDs, _ := t.ParsedUserIDs(puppetUserID)
	//检查userID是否正确，是否存在用户
	if len(parsedUserIDs) > 0 {
		for _, vUid := range parsedUserIDs {
			rc, err := User{}.UserInfo(ctx, dal.Q, "", vUid, "")
			if err != nil || rc == nil {
				return errors.Join(fmt.Errorf("用户ID不存在：%s", vUid), err)

			}
		}
	}

	if len(parsedPuppetUserIDs) > 0 {
		for _, vUid := range parsedPuppetUserIDs {
			uid, _ := strconv.ParseInt(vUid, 10, 64)
			rc, err := NewPuppetUserRepo(ctx).FindOneById(ctx, uid)
			if err != nil || rc == nil {
				return fmt.Errorf("马甲用户ID不存在：%s", vUid)

			}
		}
	}

	err = db.Transaction(func(tx *gorm.DB) error {
		onlineEventUserList, _, err := OnlineEventUser{}.List(ctx, db,
			onlineEventID, 0, nil, nil, nil, helper.BoolPtr(true),
			0, 0)
		if err != nil {
			logx.Error(ctx, "WinnerConfig.List", logx.Any("err", err))
			return err
		}

		pupperUserIDsInOnlineEvent := lo.Map(
			lo.Filter(onlineEventUserList, func(item models.OnlineEventUser, index int) bool {
				return item.IsPuppetUser
			}),
			func(item models.OnlineEventUser, index int) string {
				return item.UserID
			},
		)

		puppetUserIDsNeedToDelete := lo.Without(pupperUserIDsInOnlineEvent, parsedPuppetUserIDs...)
		puppetUserIDsNeedToAdd := lo.Without(parsedPuppetUserIDs, pupperUserIDsInOnlineEvent...)

		for _, vUid := range puppetUserIDsNeedToDelete {
			err := OnlineEventUser{}.Delete(ctx, tx, onlineEventID, vUid, true)
			if err != nil {
				logx.Error(ctx, "WinnerConfig.Delete", logx.Any("err", err))
				return err
			}
		}

		for _, vUid := range puppetUserIDsNeedToAdd {
			_, err := OnlineEventUser{}.FirstOrCreate(ctx, tx,
				onlineEventID, vUid, vUid, 0, 0,
				models.UserAddress{}, "0", true) //注意这里openid字段也设置为马甲的uid(因为马甲用户没有openid，而openid作为uniq index)
			if err != nil {
				logx.Error(ctx, "WinnerConfig.FirstOrCreate", logx.Any("err", err))
				return err
			}
		}

		_, err = dal.Use(tx).OnlineEvent.WithContext(ctx).
			Where(dal.OnlineEvent.ID.Eq(onlineEventID)).
			UpdateSimple(
				dal.OnlineEvent.SelectedUser.Value(userID),
				dal.OnlineEvent.SelectedPuppetUser.Value(puppetUserID),
			)
		if err != nil {
			logx.Error(ctx, "WinnerConfig.Updates", logx.Any("err", err))
			return err
		}
		return nil
	})
	if err != nil {
		logx.Error(ctx, "WinnerConfig", logx.Any("err", err))
		return err
	}
	return nil
}

// AddJoinedUser 增加参与人数
func (OnlineEvent) AddJoinedUser(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
) (success bool) {
	rowsAffected := db.WithContext(ctx).Model(&models.OnlineEvent{}).
		Where("id = ?", onlineEventID).
		Update("joined_user", gorm.Expr("joined_user + 1")).
		RowsAffected
	return rowsAffected > 0
}

// UpdateOrderStatus  更新订单状态
func (OnlineEvent) UpdateOrderStatus(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string, // 活动id
	openids []string,     // openid
	orderStatus int,
) bool {
	// 申请成功
	db.WithContext(ctx).Model(&models.Order{}).
		Where("online_event_id = ?", onlineEventID).
		Where("openid IN ?", openids).
		Update("order_status", orderStatus)
	// 申请失败
	db.WithContext(ctx).Model(&models.Order{}).
		Where("online_event_id = ?", onlineEventID).
		Where("openid NOT IN ?", openids).
		Update("order_status", define.OrderStatusApplyingFailed)
	// 需要支付运费的，状态更新为->待支付运费
	if orderStatus == define.OrderStatusApplyingSuccess {
		db.WithContext(ctx).Model(&models.Order{}).
			Where("online_event_id = ?", onlineEventID).
			Where("openid IN ?", openids).
			Where("express_fee > ?", 0).
			Update("order_status", define.OrderStatusUnPaidExpreeFee)
	}
	return true
}

// validateUserIDs 校验用户ID格式
func (OnlineEvent) ValidateUserIDs(userIDs string) error {
	if userIDs == "" {
		return nil
	}

	ids := strings.Split(userIDs, ",")
	for _, id := range ids {
		id = strings.TrimSpace(id)
		if id == "" {
			return errors.New("格式错误：不能包含空值")
		}
		if _, err := strconv.ParseInt(id, 10, 64); err != nil {
			return errors.New("格式错误：必须为数字")
		}
	}
	return nil
}

func (t OnlineEvent) ParsedUserIDs(userIDs string) ([]string, error) {
	if userIDs == "" { //这里要加这个处理，否则，userIDs为空时，会返回id为""的用户
		return []string{}, nil
	}
	err := t.ValidateUserIDs(userIDs)
	if err != nil {
		logx.Error(context.Background(), "validate userIDs error", logx.Any("userIDs", userIDs))
		return []string{}, err
	}

	ids := strings.Split(userIDs, ",")
	return ids, nil
}

// GetMaxSort 获取sort字段的最大值
//func (OnlineEvent) GetMaxSort(ctx context.Context, db *gorm.DB) (int, error) {
//	var maxSort int
//	err := db.WithContext(ctx).Model(&models.OnlineEvent{}).
//		Select("COALESCE(MAX(sort), 0) as max_sort").
//		Scan(&maxSort).Error
//	return maxSort, err
//}

func (OnlineEvent) GetMaxSortRecord(ctx context.Context, db *gorm.DB) (*models.OnlineEvent, error) {
	var record *models.OnlineEvent
	q := dal.Use(db)
	record, err := q.WithContext(ctx).OnlineEvent.Unscoped().
		Order(q.OnlineEvent.Sort.Desc()).
		First()

	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil // 返回nil表示没有找到记录
		}
		return nil, err
	}

	return record, nil
}
